/*

This file is part of org-json.

org-json is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

using System;
using NUnit.Framework;
using System.IO;
using System.Reflection;


namespace Org.JSON.Test
{
	class Assert : NUnit.Framework.Assert
	{	
		public static void Throws<T>(Action act, string message) where T: Exception
		{
			try
			{
				act();
			}
			catch(T ex)
			{
				if(ex.Message == message)
					return;
			}
			Assert.Fail("Expected exception of type '" + typeof(T).FullName + "' with message '" + message +"'");
		}
	}
	
	[TestFixture()]
	public class Deserialization
	{		
		[Test()]
		public void Null()
		{
			var value = Value.From("null");
			
			Assert.IsInstanceOf<Null>(value);
		}
		
		[Test()]
		public void ArraySimple()
		{
			var value = Value.From("[]");
			
			Assert.IsInstanceOf<Array>(value);
		}
		
		[Test()]
		public void ArrayOneItem()
		{
			var value = Value.From("[null]");
			
			Assert.IsInstanceOf<Null>((value as Array)[0]);
		}
		
		[Test()]
		public void ArrayManyItems()
		{
			var value = Value.From("[null,null,null]");
			Assert.IsInstanceOf<Null>((value as Array)[2]);
		}
		
		[Test()]
		public void ArrayInnerArray()
		{
			var value = Value.From("[[[]]]");
			Assert.IsInstanceOf<Array>((value as Array)[0]);
		}
		
		[Test()]
		public void BooleanTrue()
		{
			var value = Value.From("true");
			Assert.IsTrue((value as Boolean).Value);
		}
		
		[Test()]
		public void BooleanFalse()
		{
			var value = Value.From("false");
			Assert.IsFalse((value as Boolean).Value);
		}
		
		[Test()]
		public void StringBasic()
		{
			var value = Value.From("\"a\"");
			Assert.AreEqual("a",(value as String).Value);
		}
		
		[Test()]
		public void StringSingleScapeSequence()
		{
			var value = Value.From("\"\\\"\\\\\\n\\b\\f\\t\\r\\/\"");
			Assert.AreEqual("\"\\\n\b\f\t\r/" ,(value as String).Value);
		}
		
		[Test()]
		public void StringUnicodeScape()
		{
			var value = Value.From("\"\\u0020\"");
			
			Assert.AreEqual("\u0020", (value as String).Value);
		}
		
		[Test()]
		public void ObjectEmpty()
		{
			var value = Value.From("{   }");
			Assert.IsInstanceOf<Object>(value);
		}
		
		[Test()]
		public void ObjectOneItem()
		{
			var value = Value.From("  {\"prop\":null}  ");
			Assert.IsInstanceOf<Null>((value as Object)["prop"]);
		}
		
		[Test()]
		public void ObjectManyItems()
		{
			var value = Value.From("{\"a\":null,\"b\":null,\"c\":null}");
			Assert.IsInstanceOf<Null>((value as Object)["c"]);
		}
		
		[Test()]
		public void ObjectInnerObject()
		{
			var value = Value.From("{\"a\":{}}");
			Assert.IsInstanceOf<Object>((value as Object)["a"]);
		}
		
		[Test()]
		public void NumberSimple()
		{
			var value = Value.From("1");
			Assert.AreEqual(1, (value as Number).Value);
		}
		
		[Test()]
		public void NumberNegavite()
		{
			var value = Value.From("-7");
			Assert.AreEqual(-7, (value as Number).Value);
		}
		
		[Test()]
		public void NumberZero()
		{
			var value = Value.From("0");
			Assert.AreEqual(0, (value as Number).Value);
		}
		
		[Test()]
		public void NumberDecimal()
		{
			var value = Value.From("12.44");
			Assert.AreEqual(12.44, (value as Number).Value);
		}
		
		[Test()]
		public void NumberFloat()
		{
			var value = Value.From("8e-3");
			Assert.AreEqual(8e-3, (value as Number).Value);
		}
		
		[Test()]
		public void NumberFloatDecimal()
		{
			var value = Value.From("-8.78E+32");
			Assert.AreEqual(-8.78e32, (value as Number).Value);
		}
		
		[Test()]
		public void InvalidLex()
		{
			Assert.Throws<LexicalExeption>(()=>Value.From("?"));
		}
		
		[Test()]
		public void NetExample1()
		{
			var value = Value.From(new StreamReader(
				Assembly
					.GetExecutingAssembly()
					.GetManifestResourceStream("Org.JSON.Test.NetExample1.txt")
			)
			.ReadToEnd());
			
			Assert.AreEqual("markup", 
			    ((((((value as Object)
			     	["glossary"] as Object)
			    	["GlossDiv"] as Object)
			   		["GlossList"] as Object)
			  		["GlossEntry"] as Object)
			 		["GlossSee"] as String).Value);
		}
		
		[Test()]
		public void NetExample2()
		{
			var value = Value.From(new StreamReader(
				Assembly
					.GetExecutingAssembly()
					.GetManifestResourceStream("Org.JSON.Test.NetExample2.txt")
			)
			.ReadToEnd());
			
			Assert.AreEqual("CloseDoc()", 
			    ((((((value as Object)
			     	["menu"] as Object)
			    	["popup"] as Object)
			   		["menuitem"] as Array)
			  		[2] as Object)
			 		["onclick"] as String).Value);
		}
		
		[Test()]
		public void NetExample3()
		{
			var value = Value.From(new StreamReader(
				Assembly
					.GetExecutingAssembly()
					.GetManifestResourceStream("Org.JSON.Test.NetExample3.txt")
			)
			.ReadToEnd());
			
			Assert.AreEqual("sun1.opacity = (sun1.opacity / 100) * 90;", 
			    ((((value as Object)
			     	["widget"] as Object)
			    	["text"] as Object)
			 		["onMouseUp"] as String).Value);
		}
		
		[Test()]
		public void NetExample4()
		{
			var value = Value.From(new StreamReader(
				Assembly
					.GetExecutingAssembly()
					.GetManifestResourceStream("Org.JSON.Test.NetExample4.txt")
			)
			.ReadToEnd());
			
			Assert.AreEqual("About Adobe CVG Viewer...", 
			    (((((value as Object)
			     	["menu"] as Object)
			    	["items"] as Array)
			 		[21] as Object)
			 		["label"] as String).Value);
		}
		
		[Test()]
		public void NetExample5()
		{
			var value = Value.From(new StreamReader(
				Assembly
					.GetExecutingAssembly()
					.GetManifestResourceStream("Org.JSON.Test.NetExample5.txt")
			)
			.ReadToEnd());
			
			Assert.AreEqual("/WEB-INF/tlds/cofax.tld", 
			    ((((value as Object)
			     	["web-app"] as Object)
			    	["taglib"] as Object)
			 		["taglib-location"] as String).Value);
		}
		
		[Test()]
		public void EndExpectedException()
		{
			Assert.Throws<Exception>(() => Value.From("[]p"), "Expected by the end of json in the character 2.");
			
		}
		
		[Test()]
		public void EndExpectedExceptionWithValidToken()
		{
			Assert.Throws<Exception>(() => Value.From("[]1"), "Expected by the end of json in the character 2.");
			
		}
	}
}

